<?php
/**
 * Created by PhpStorm.
 * User: peter
 * Date: 2019/1/12
 * Time: 4:12 PM
 */

namespace app\activity\controller;


use app\model\AccountCapitalFlow;
use app\model\Bill;
use app\model\RechargeOrder;
use EasyWeChat\Factory;
use Endroid\QrCode\QrCode;
use extend\Functions;
use extend\STATUS_CODE;
use think\facade\Env;
use think\Request;

class Recharge extends Auth
{
    /**
     * @purpose APP余额充值同步回调
     * @param Request $request
     * @return array
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
     * @throws \think\Exception
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     * @throws \think\exception\PDOException
     */
    public function rechargeByAppSync(Request $request)
    {
        $order_no = $request->get('order_no');
        if (!$order_no) {
            return self::response(
                STATUS_CODE::PARAMETER_ERROR,
                '参数错误'
            );
        }
        $order  = new RechargeOrder();
        $member = new \app\model\Member();
        $order->startTrans();
        $order_info = $order
            ->lock(true)
            ->where('order_no', $order_no)
            ->field('id,uid,quota,status,order_no,pay_method')
            ->find();
        if (!$order_info) {
            $order->rollback();
            return self::response(
                STATUS_CODE::PARAMETER_ERROR,
                '订单不存在'
            );
        }
        if ($order_info->status === 99) {
            $order->rollback();
            return self::response();
        }
        if ($order_info->status !== 1) {
            $order->rollback();
            return self::response(
                STATUS_CODE::ORDER_STATUS_ERROR,
                '订单状态错误'
            );
        }
        $member_info = $member
            ->where('uid', $order_info->uid)
            ->field('uid,balance,frozen')
            ->find();
        switch ($order_info->pay_method) {
            case 1: // 检测微信支付是否成功
                // 主动查询订单是否支付成功
                $app        = Factory::payment(config('wechat.payment.app'));
                $pay_result = $app->order->queryByOutTradeNumber($order_info->order_no);
                if (
                    $pay_result['return_code'] === 'SUCCESS' &&
                    $pay_result['return_msg'] === 'OK' &&
                    $pay_result['trade_state'] === 'SUCCESS' &&
                    $pay_result['result_code'] === 'SUCCESS'
                ) {
                    $order_result = $order
                        ->isUpdate(true)
                        ->save(
                            [
                                'status'     => 99,
                                'pay_at'     => strtotime($pay_result['time_end']),
                                'pay_no'     => $pay_result['transaction_id'],
                                'pay_method' => 1,
                                'pay_money'  => $pay_result['cash_fee'],
                            ],
                            ['id' => $order_info->id]);
                    // 增加账户余额
                    $member_result = $member
                        ->where('uid', $order_info->uid)
                        ->setInc('balance', $order_info->quota);
                    // 记录账户资金流水
                    $account_capital_flow = AccountCapitalFlow::M()
                        ->data([
                            'uid'          => $order_info->uid,
                            'quota'        => $order_info->quota,
                            'balance' => $order_info->quota + ($member_info->balance - $member_info->frozen),
                            'type'         => 1,
                            'descriptions' => '充值余额-微信',
                        ])
                        ->save();
                    // 记录支付账单
                    Bill::addToBill(
                        $order_info->uid,
                        5,
                        $order_info->order_no,
                        $pay_result['cash_fee'],
                        1,
                        '余额充值'
                    );
                    if ($order_result && $member_result && $account_capital_flow) {
                        $order->commit();
                        return self::response();
                    }
                    // 记录账户资金流水
                    $order->rollback();
                    return self::response();
                } else if ($pay_result['return_code'] === 'FAIL') {
                    return Functions::result(
                        STATUS_CODE::PARAMETER_ERROR,
                        $pay_result['return_msg']
                    );
                } else {
                    return Functions::result(
                        STATUS_CODE::PARAMETER_ERROR,
                        $pay_result['trade_state_desc']
                    );
                }
                break;
            case 2:
                include Env::get('root_path') . 'extend/alipay/AopSdk.php';
                include Env::get('root_path') . 'extend/alipay/aop/request/AlipayTradeAppPayRequest.php';
                $aop                     = new \AopClient();
                $aop->gatewayUrl         = 'https://openapi.alipay.com/gateway.do';
                $aop->appId              = config('alipay.app.appid');
                $aop->rsaPrivateKey      = config('alipay.app.private_key');
                $aop->format             = 'json';
                $aop->charset            = 'UTF-8';
                $aop->signType           = 'RSA';
                $aop->alipayrsaPublicKey = config('alipay.app.public_key');
                $content                 = [];
                $content['out_trade_no'] = $order_info->order_no;
                $request                 = new \AlipayTradeQueryRequest();
                $request->setBizContent(json_encode($content));
                $result       = $aop->execute($request);
                $responseNode = str_replace(".", "_", $request->getApiMethodName()) . "_response";

                $result = $result->$responseNode;

                if ((int)$result->code !== 10000) {
                    return self::response(
                        $result->code,
                        $result->msg
                    );
                }
                // 交易支付成功
                if ($result->trade_status === 'TRADE_SUCCESS') {
                    $order_result = $order
                        ->isUpdate(true)
                        ->save(
                            [
                                'status'     => 99,
                                'pay_at'     => time(),
                                'pay_no'     => $result->trade_no,
                                'pay_method' => 2,
                                'pay_money'  => $result->total_amount * 100,
                            ],
                            ['id' => $order_info->id]);
                    // 增加账户余额
                    $member_result = $member
                        ->where('uid', $order_info->uid)
                        ->setInc('balance', $order_info->quota);
                    // 记录账户资金流水
                    $account_capital_flow = AccountCapitalFlow::M()
                        ->data([
                            'uid'          => $order_info->uid,
                            'quota'        => $order_info->quota,
                            'balance' => $order_info->quota + ($member_info->balance - $member_info->frozen),
                            'type'         => 1,
                            'descriptions' => '充值余额-支付宝',
                        ])
                        ->save();
                    // 记录支付账单
                    Bill::addToBill(
                        $order_info->uid,
                        5,
                        $order_info->order_no,
                        $result->total_amount * 100,
                        2,
                        '余额充值'
                    );
                    if ($order_result && $member_result && $account_capital_flow) {
                        $order->commit();
                        return self::response();
                    }
                    // 记录账户资金流水
                    $order->rollback();
                    return self::response();
                }
                return self::response();
                break;
            default:
                return self::response(
                    STATUS_CODE::PARAMETER_ERROR,
                    '未知的支付方式'
                );
                break;
        }
    }

    /**
     * @purpose 微信端余额充值
     * @param Request $request
     * @return array
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
     * @throws \think\exception\PDOException
     */
    public function rechargeByWechat (Request $request) {
        $quota      = $request->post('quota');
        $quota      = (int) ($quota * 100);
        // 创建支付订单
        $data               = [];
        $data['uid']        = self::$uid;
        $data['quota']      = $quota;
        $data['pay_method'] = 1;
        $order_no           = '10001' . date('YmdHis') . Functions::random(8);
        RE_ORDER_NO:
        $order_no = '10001' . date('YmdHis') . Functions::random(8);
        RechargeOrder::M()->startTrans();
        if (RechargeOrder::M()->where('order_no', $order_no)->count(1) > 1) {
            goto RE_ORDER_NO;
        }
        $data['order_no'] = $order_no;
        $order_result           = RechargeOrder::M()
            ->data($data)
            ->save();
        $app                 = Factory::payment(config('wechat.payment.official_account'));
        $data                = [
            'body'         => '欢乐中国网-活动报名!',
            'trade_type'   => 'JSAPI',
            'out_trade_no' => $order_no,
            'total_fee'    => $quota,
            'notify_url'   => 'http://server.enjoychina.cc/activity-api/recharge.wechat.async',
            'openid'       => cookie('pay_openid'),
            'attach'       => self::$uuid,
        ];
        $result              = $app->order->unify($data);
        $result              = $app->jssdk->sdkConfig($result['prepay_id']);
        $result['timeStamp'] = $result['timestamp'];
        unset($result['timestamp']);
        RechargeOrder::M()->commit();
        return Functions::result([
            'order_no' => $order_no,
            'voucher' => $result,
        ]);
    }
    /**
     * @purpose H5界面充值
     * @param Request $request
     * @return array
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
     * @throws \think\exception\PDOException
     */
    public function rechargeByH5 (Request $request) {
        $quota      = $request->post('quota');
        $quota      = (int) ($quota * 100);
        $pay_method = $request->post('pay_method');
        // 创建支付订单
        $data               = [];
        $data['uid']        = self::$uid;
        $data['quota']      = $quota;
        $data['pay_method'] = (int)$pay_method;
        $order_no           = '10001' . date('YmdHis') . Functions::random(8);
        RE_ORDER_NO:
        $order_no = '10001' . date('YmdHis') . Functions::random(8);
        RechargeOrder::M()->startTrans();
        if (RechargeOrder::M()->where('order_no', $order_no)->count(1) > 1) {
            goto RE_ORDER_NO;
        }
        $data['order_no'] = $order_no;
        $order_result           = RechargeOrder::M()
            ->data($data)
            ->save();

        switch ($pay_method) {
            case 1: // 微信支付
                $is_wap              = Functions::isMobile();
                $app                 = Factory::payment(config('wechat.payment.official_account'));
                $data                = [
                    'body'         => '欢乐中国账户余额充值!',
                    'trade_type'   => $is_wap ? 'MWEB' : 'NATIVE',
                    'out_trade_no' => $order_no,
                    'total_fee'    => $quota,
                    'notify_url'   => 'http://server.enjoychina.cc/activity-api/recharge.wechat.async',
                    'attach'       => self::$uuid
                ];
                $result              = $app->order->unify($data);
                if ($is_wap) {
                    RechargeOrder::M()->commit();
                    return self::response([
                        'pay_method' => $pay_method,
                        'is_mobile' => $is_wap,
                        'url' => $result['mweb_url'],// .'&redirect_url='.urlencode('http://h5.enjoychina.cc/activity-api/h5.recharge.pay.sync?order_no='.$order_no),
                        'order_no' => $order_no
                    ]);
                }
                $qr_code = new QrCode($result['code_url']);
                $qr_code->setWriterByName('png');
                $qr_code->setEncoding('UTF-8');
//                $qr_code->setErrorCorrectionLevel('high');
                $data = $qr_code->writeString();
                $data = 'data:image/png;base64,' . base64_encode($data);
                RechargeOrder::M()->commit();
                return self::response([
                    'pay_method' => $pay_method,
                    'is_mobile' => $is_wap,
                    'qr' => $data,
                    'order_no' => $order_no
                ]);
                break;
            case 2: // 支付宝支付
                // 支付宝支付
                include Env::get('root_path'). 'extend/alipay/AopSdk.php';
                include Env::get('root_path'). 'extend/alipay/aop/request/AlipayTradePrecreateRequest.php';
                $aop                            = new \AopClient();
                $aop->gatewayUrl                = 'https://openapi.alipay.com/gateway.do';
                $aop->appId                     = config('alipay.app.appid');
                $aop->rsaPrivateKey             = config('alipay.app.private_key');
                $aop->format                    = "json";
                $aop->charset                   = "UTF-8";
                $aop->signType                  = "RSA";
                $aop->alipayrsaPublicKey        = config('alipay.app.public_key');
                $content                        = [];
                $content['body']                = '欢乐中国账户余额充值';
                $content['subject']             = '欢乐中国账户余额充值';
                $content['out_trade_no']        = $order_no;
                $content['timeout_express']     = '30m';
                $content['total_amount']        = $quota / 100;
                $content['product_code']        = 'FAST_INSTANT_TRADE_PAY';
                $request                        = new \AlipayTradePrecreateRequest();
                $request->setNotifyUrl('http://server.enjoychina.cc/activity-api/recharge.alipay.async');
//                $request->setReturnUrl('http://h5.enjoychina.cc/activity-api/activity.h5.alipay.sync');
                $request->setBizContent(json_encode($content));
                $response                       = $aop->pageExecute($request);
                die($response);
                break;
        }

    }
    /**
     * @purpose APP余额充值
     * @param Request $request
     * @return array
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
     */
    public function rechargeByApp(Request $request)
    {
        $quota      = $request->post('quota');
        $pay_method = $request->post('pay_method');
        // 创建支付订单
        $data               = [];
        $data['uid']        = self::$uid;
        $data['quota']      = (int)($quota * 100);
        $data['pay_method'] = (int)$pay_method;
        $order_no           = '10001' . date('YmdHis') . Functions::random(8);
        RE_ORDER_NO:
        $order_no = '10001' . date('YmdHis') . Functions::random(8);
        if (RechargeOrder::M()->where('order_no', $order_no)->count(1) > 1) {
            goto RE_ORDER_NO;
        }
        $data['order_no'] = $order_no;
        $result           = RechargeOrder::M()
            ->data($data)
            ->save();
        if ($result) {
            switch ($pay_method) {
                case 1:
                    $result              = Functions::wechatAppPay([
                        'body'         => '欢乐中国账户余额充值',
                        'detail'       => '欢乐中国账户余额充值',
                        'out_trade_no' => $data['order_no'],
                        'total_fee'    => $data['quota'],
                        'attach'       => self::$uuid,
                        'notify_url'   => 'http://server.enjoychina.cc/activity-api/recharge.wechat.async',
                        'trade_type'   => 'APP',
                    ]);
                    $result['timestamp'] = time();
                    return Functions::result(
                        STATUS_CODE::SUCCESS,
                        [
                            'order_no' => $data['order_no'],
                            'pay_type' => $pay_method,
                            'voucher'  => $result,
                        ]
                    );
                    break;
                case 2:
                    include Env::get('root_path') . 'extend/alipay/AopSdk.php';
                    include Env::get('root_path') . 'extend/alipay/aop/request/AlipayTradeAppPayRequest.php';
                    $aop                        = new \AopClient();
                    $aop->gatewayUrl            = 'https://openapi.alipay.com/gateway.do';
                    $aop->appId                 = config('alipay.app.appid');
                    $aop->rsaPrivateKey         = config('alipay.app.private_key');
                    $aop->format                = "json";
                    $aop->charset               = "UTF-8";
                    $aop->signType              = "RSA";
                    $aop->alipayrsaPublicKey    = config('alipay.app.public_key');
                    $content                    = [];
                    $content['body']            = '欢乐中国账户余额充值';
                    $content['subject']         = '欢乐中国账户余额充值';
                    $content['out_trade_no']    = $data['order_no'];
                    $content['timeout_express'] = '30m';
                    $content['total_amount']    = $data['quota'] / 100;
                    $content['product_code']    = 'QUICK_MSECURITY_PAY';
                    $request                    = new \AlipayTradeAppPayRequest();
                    $request->setNotifyUrl('http://server.enjoychina.cc/activity-api/recharge.alipay.async');
                    $request->setBizContent(json_encode($content));
                    $response = $aop->sdkExecute($request);
                    return Functions::result(
                        STATUS_CODE::SUCCESS,
                        [
                            'order_no' => $data['order_no'],
                            'pay_type' => $pay_method,
                            'voucher'  => $response,
                        ]
                    );
                    break;
            }
        }
        return self::response(
            STATUS_CODE::CREATE_FAIL,
            '订单创建失败'
        );
    }
}